package com.yunji.product.business;

import com.yunji.base.cache.BaseCache;
import com.yunji.base.domain.BelongDO;
import com.yunji.base.dto.AgentDTO;
import com.yunji.base.service.AgentService;
import com.yunji.base.service.BelongService;
import com.yunji.base.service.SiteService;
import com.yunji.cabinet.bo.CapacityCeilingBO;
import com.yunji.cabinet.cache.CabinetCache;
import com.yunji.cabinet.context.calculate.CabinetCalculate;
import com.yunji.cabinet.service.ICabinetService;
import com.yunji.common.base.BaseBusiness;
import com.yunji.common.constant.LogicCode;
import com.yunji.common.enums.common.UserType;
import com.yunji.common.model.dto.LoginInfo;
import com.yunji.common.utils.DecimalUtils;
import com.yunji.common.utils.bean.BeanUtils;
import com.yunji.product.bo.ProductAgentListQueryBO;
import com.yunji.product.bo.ProductAgentSelectQueryBO;
import com.yunji.product.bo.ProductAgentUpdateBO;
import com.yunji.product.bo.ProductListQueryBO;
import com.yunji.product.domain.ProductDO;
import com.yunji.product.domain.ProductAgentDO;
import com.yunji.product.dto.ProductAccreditDTO;
import com.yunji.product.dto.ProductAgentDTO;
import com.yunji.product.enums.GrantTypes;
import com.yunji.product.enums.ProductCompareType;
import com.yunji.product.params.ContainerProductParam;
import com.yunji.product.params.PermissionsParam;
import com.yunji.product.service.IProductAgentService;
import com.yunji.product.service.IProductService;
import com.yunji.product.vo.ProductAccreditVO;
import com.yunji.product.vo.ProductCompareVO;
import com.yunji.system.service.TokenService;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Project: yunji-coffee
 * @Package com.yunji.product.business
 * @FileName ProductAgentBusiness.java
 * @Copyright Copyright © 2024 云集互联. All Rights Reserved
 * @Company com
 * @Version 1.0
 * @Since JDK1.8.0_201
 * @CreateTime 2024-06-10 23:38:50
 * @Description 产品代理处理
 * @Modification History
 * Author					History Time			Version			Description
 * -------------------------------------------------------------------------------
 * HuaAo0803@163.com	2024-06-10 23:38:50		1.0				1.0
 */
@Component
public class ProductAgentBusiness extends BaseBusiness {
    @Resource
    TokenService tokenService;

    @Resource
    IProductService productService;

    @Resource
    IProductAgentService productAgentService;

    @Resource
    ICabinetService cabinetService;

    @Resource
    SiteService siteService;

    @Resource
    AgentService agentService;

    @Resource
    BelongService belongService;

    /**
     * @param dto 商品代理信息
     * @Title update
     * @Desc 更新商品代理信息
     * @Date 2024-06-11 17:52:53.960
     */
    public void update(ProductAgentDTO dto) {
        Long productId = dto.getProductId();
        logs.info("【变更售价】商品ID:{}", productId);
        Assert.isTrue(BeanUtils.isNotNull(productId), "未找到商品信息");

        ProductDO origins = productService.select(productId);
        logs.info("【变更售价】原始商品信息:{}", origins);
        Assert.isTrue(BeanUtils.isNotNull(origins), "未找到原始商品信息");

        BigDecimal discountPrice = dto.getDiscountPrice();
        BigDecimal minPriceLimit = origins.getMinDiscountPrice();
        BigDecimal maxPriceLimit = origins.getMaxDiscountPrice();
        logs.info("【变更售价】折扣价格:{},最小价格限制:{},最大价格限制:{}", discountPrice, minPriceLimit, maxPriceLimit);

        Assert.isTrue(!DecimalUtils.less(discountPrice, minPriceLimit), "设置折扣价不能小于最小折扣价");
        Assert.isTrue(!DecimalUtils.more(discountPrice, maxPriceLimit), "设置折扣价不能超过最大折扣价");

        LoginInfo user = tokenService.getUser();
        Long belongId = user.getBelongId();
        String userType = user.getUserType();
        String userText = UserType.getText(userType);
        logs.info("【变更售价】当前登录所属ID:{},用户类型={}:{}", belongId, userType, userText);

        if (UserType.AGENT.getCode().equals(userType)) {

            ProductAgentDO original = productAgentService.select(ProductAgentSelectQueryBO.builder().belongId(belongId)
                    .productId(productId).status(LogicCode.NO).userType(UserType.AGENT.getCode()).build());
            Assert.isTrue(BeanUtils.isNotNull(original), "未找到该商品授权,请联系管理员确认!");

            Integer grantType = dto.getGrandType();
            String grantText = GrantTypes.get(grantType);
            logs.info("【变更售价】授权类型={}:{}", grantType, grantText);

            Long[] authIds = dto.getManagerIds();
            if (Objects.equals(GrantTypes.ALL_GRANT.getCode(), grantType)) {
                authIds = belongService.getSiteIdsById(belongId);
            }

            if (BeanUtils.isNotNull(authIds)) {
                for (Long authId : authIds) {
                    Assert.isTrue(productAgentService.updateByBO(ProductAgentUpdateBO.builder().discountPrice(discountPrice).agentPrice(discountPrice)
                            .managerId(authId).productId(productId).userType(UserType.SITE.getCode()).build()), "修改失败");
                }
            }
        } else {

            BelongDO belong = BaseCache.getBelong(belongId);
            Assert.isTrue(Objects.equals(LogicCode.YES, belong.getCustomPrice()), "无定价权限,请联系管理员确认!");

            ProductAgentDO original = productAgentService.select(ProductAgentSelectQueryBO.builder().belongId(belongId)
                    .productId(productId).status(LogicCode.NO).userType(UserType.SITE.getCode()).build());
            Assert.isTrue(BeanUtils.isNotNull(original), "未找到该商品授权,请联系管理员确认!");

            // 标记网点设置过自定义价格
            Assert.isTrue(productAgentService.updateByBO(ProductAgentUpdateBO.builder().discountPrice(discountPrice).managerPrice(discountPrice)
                    .changeStatus(LogicCode.YES).belongId(belongId).productId(productId).userType(UserType.SITE.getCode()).build()), "修改失败");
        }
    }

    /**
     * @param update 更新集合
     * @param dto    参数信息
     * @Title handleSitePrice
     * @Desc 处理网点价格
     * @Date 2024-08-29 13:44:39.331
     */
    private void handleSitePrice(List<ProductAgentDO> update, ProductAgentDTO dto) {
        LoginInfo user = tokenService.getUser();
        Long belongId = user.getBelongId();
        Long productId = dto.getProductId();
        logs.info("【初始化价格】当前用户所属ID:{}, 商品ID:{}", belongId, productId);


        BelongDO belong = BaseCache.getBelong(belongId);
        if (BeanUtils.isNull(belong)) {
            return;
        }

        List<BelongDO> belongList = belongService.listByAgentId(UserType.SITE.getCode(), belong.getAgentId());
        if (BeanUtils.isNull(belongList)) {
            return;
        }
        Map<Long, BelongDO> map = belongList.stream().collect(Collectors.toMap(BelongDO::getSiteId, e -> e, (k1, k2) -> k1));

        // 找到授权商品状态
        ProductAgentListQueryBO params = new ProductAgentListQueryBO();
        params.setUserType(UserType.SITE.getCode());
        params.setAgentId(dto.getAgentId());
        params.setProductId(productId);
        List<ProductAgentDO> list = productAgentService.search(params);
        logs.info("【初始化价格】经理用户商品信息:{}", list);
        if (BeanUtils.isNull(list)) {
            return;
        }

        for (ProductAgentDO agent : list) {
            Long siteId = agent.getSiteId();
            BelongDO siteBelong = map.get(siteId);
            Integer customPrice = siteBelong.getCustomPrice();

            BigDecimal agentPrice = agent.getAgentPrice();
            BigDecimal sitePrice = agent.getManagerPrice();
            logs.info("【初始化价格】自定义标识:{}, 代理设置价格:{}, 网点设置价格:{}", customPrice, agentPrice, sitePrice);
            if (!DecimalUtils.compare(agentPrice) || (!DecimalUtils.compare(sitePrice) && Objects.equals(LogicCode.YES, customPrice))) {
                continue;
            }
            agent.setDiscountPrice(dto.getAgentPrice());
            update.add(agent);
        }
    }

    /**
     * @param dto 商品信息
     * @Title agentPrice
     * @Desc 设置代理商品售价
     * @Date 2024-08-29 13:49:21.085
     */
    public void agentPrice(ProductAgentDTO dto) {
        LoginInfo user = tokenService.getUser();
        Long belongId = user.getBelongId();
        String userType = user.getUserType();
        String userText = UserType.getText(userType);
        logs.info("【初始化价格】当前用户所属ID:{},用户类型={}:{}", belongId, userType, userText);
        Assert.isTrue(UserType.AGENT.getCode().equalsIgnoreCase(userType), "非法访问");

        Long productId = dto.getProductId();
        BigDecimal discountPrice = dto.getAgentPrice();
        logs.info("【初始化价格】商品ID:{},代理授权价：{}", productId, discountPrice);

        // 校验授权价是否合法
        ProductDO origins = productService.select(productId);
        logs.info("【初始化价格】原始商品信息:{}", origins);
        Assert.isTrue(BeanUtils.isNotNull(origins), "未找到商品信息");

        BelongDO belong = BaseCache.getBelong(belongId);
        logs.info("【初始化价格】所属信息:{}", belong);
        Assert.isTrue(BeanUtils.isNotNull(belong), "未找到用户所属信息");
        Long agentId = belong.getAgentId();
        logs.info("【初始化价格】所属代理ID:{}", agentId);

        BigDecimal minPriceLimit = origins.getMinDiscountPrice();
        BigDecimal maxPriceLimit = origins.getMaxDiscountPrice();
        logs.info("【初始化价格】最小折扣价:{},最大折扣价{}", minPriceLimit, maxPriceLimit);

        Assert.isTrue(!DecimalUtils.less(discountPrice, minPriceLimit), "设置折扣价不能小于最小折扣价");
        Assert.isTrue(!DecimalUtils.more(discountPrice, maxPriceLimit), "设置折扣价不能超过最大折扣价");

        List<ProductAgentDO> update = new ArrayList<>();

        dto.setAgentId(agentId);
        handleSitePrice(update, dto);
        productAgentService.updateByBO(ProductAgentUpdateBO.builder().agentPrice(discountPrice).discountPrice(discountPrice)
                .productId(productId).agentId(agentId).userType(UserType.AGENT.getCode()).build());

        for (ProductAgentDO agent : update) {
            productAgentService.update(agent);
        }
    }

    /**
     * @param productId 商品信息ID
     * @Title selectCurrent
     * @Desc 查询当前代理商品信息详情
     * @Date 2024-06-11 17:59:59.891
     * @Return ProductAgent 商品信息详情
     */
    public ProductAgentDO selectCurrent(Long productId) {
        LoginInfo user = tokenService.getUser();
        String userType = user.getUserType();
        Long userId = user.getUserId();
        if (userType.equals(UserType.AGENT.getCode())) {
            return productAgentService.select(ProductAgentSelectQueryBO.builder().productId(productId)
                    .userType(UserType.AGENT.getCode()).agentId(userId).build());
        } else {
            return productAgentService.select(ProductAgentSelectQueryBO.builder().productId(productId)
                    .userType(UserType.SITE.getCode()).mangerId(userId).build());
        }
    }

    /**
     * @param dto 商品授权信息
     * @Title productAccredit
     * @Desc 校验商品授权
     * @Date 2024-09-06 19:55:11.397
     * @Return ProductAccreditVO
     */
    public List<ProductAccreditVO> productAccredit(ProductAccreditDTO dto) {
        LoginInfo user = tokenService.getUser();
        Long belongId = user.getBelongId();
        String userType = user.getUserType();

        Long siteId = dto.getSiteId();
        if (Objects.equals(UserType.SITE.getCode(), userType)) {
            BelongDO belong = BaseCache.getBelong(belongId);
            siteId = belong.getSiteId();
        } else {
            Assert.isTrue(BeanUtils.isNotNull(siteId), "请上传换绑的网点ID");
        }

        Long[] productIds = dto.getProductIds();

        List<ProductAccreditVO> list = new ArrayList<>();
        for (Long productId : productIds) {
            // 单个校验授权
            ProductAgentDO productAgent = productAgentService.select(ProductAgentSelectQueryBO.builder().status(LogicCode.NO)
                    .productId(productId).mangerId(siteId).build());

            ProductAccreditVO vo = new ProductAccreditVO();
            vo.setProductId(productId);
            vo.setSiteId(siteId);
            vo.setAccreditStatus(BeanUtils.isNotNull(productAgent) ? LogicCode.NO : LogicCode.YES);
            vo.setCeilingQuantity(CabinetCalculate.getCapacityCeiling(
                    new CapacityCeilingBO(dto.getTypeCode(),productId)).intValue());
            list.add(vo);
        }
        return list;
    }

    /**
     * @param param
     * @Title comparePermissions
     * @Desc 商品权限对比列表
     * @Date 2024-09-18 17:24:41.629
     * @Return List<PermissionsVO>
     */
    public List<ProductCompareVO> comparePermissions(PermissionsParam param) {
        Integer compareType = param.getProductCompareType();
        Long siteId = param.getSiteId();
        Long newAgentId = param.getNewAgentId();
        Long oldAgentId = param.getOldAgentId();
        Assert.isTrue(BeanUtils.isNotNull(compareType), "请上传对比类型");
        Assert.isTrue(BeanUtils.isNotNull(siteId), "请上传换绑的网点ID");
        Assert.isTrue(BeanUtils.isNotNull(oldAgentId), "请上传旧代理ID");
        Assert.isTrue(BeanUtils.isNotNull(newAgentId), "请上传新代理ID");

        List<ProductDO> list = new ArrayList<>();
        ProductListQueryBO dto = new ProductListQueryBO();
        dto.setPageNum(param.getPageNum());
        dto.setPageSize(param.getPageSize());
        dto.setAgentId(oldAgentId);
        dto.setUserType(UserType.AGENT.getCode());
        dto.setAccreditStatus(LogicCode.NO);
        if (Objects.equals(ProductCompareType.CONTAINER_PRODUCT.getCode(), compareType)) {
            ContainerProductParam containerProductParam = new ContainerProductParam();
            containerProductParam.setSiteId(siteId);
            List<Long> productIds = cabinetService.searchProductIdsBySiteId(siteId);
            if (!productIds.isEmpty()) {
                dto.setProductIds(productIds);
                list = productService.searchProductPrice(dto);
            }
        } else {
            list = productService.searchProductPrice(dto);
        }

        List<ProductDO> newList;
        ProductListQueryBO newDto = new ProductListQueryBO();
        newDto.setAgentId(newAgentId);
        newDto.setUserType(UserType.AGENT.getCode());
        newDto.setAccreditStatus(LogicCode.NO);
        newList = productService.searchProductPrice(newDto);

        List<Long> productIds = newList.stream().map(ProductDO::getId).collect(Collectors.toList());
        List<ProductCompareVO> voList = new ArrayList<>();
        for (ProductDO product : list) {
            ProductCompareVO vo = new ProductCompareVO();
            Long productId = product.getId();
            Integer newStatus = productIds.contains(productId) ? LogicCode.NO : LogicCode.YES;
            BeanUtils.clone(product, vo);
            vo.setOldStatus(LogicCode.NO);
            vo.setNewStatus(newStatus);
            voList.add(vo);
        }
        return voList;
    }

    /**
     * @param param
     * @Title compareResult
     * @Desc 校验货柜商品授权
     * @Date 2024-09-19 14:11:28.997
     * @Return Response<Boolean>
     */
    public Boolean compareResult(PermissionsParam param) {
        Long siteId = param.getSiteId();
        Long newAgentId = param.getNewAgentId();
        logs.info("【商品权限对比】站点ID:{}", siteId);
        logs.info("【商品权限对比】新代理ID:{}", newAgentId);
        Assert.isTrue(BeanUtils.isNotNull(siteId), "请上传换绑的网点ID");
        Assert.isTrue(BeanUtils.isNotNull(newAgentId), "请上传新代理ID");

//        List<Product> list;
        ContainerProductParam containerProductParam = new ContainerProductParam();
        containerProductParam.setSiteId(siteId);
        List<Long> productIds = cabinetService.searchProductIdsBySiteId(siteId);
//        for (Long productId : productIds) {
//            System.out.println("");
//        }

        ContainerProductParam newParam = new ContainerProductParam();
        newParam.setAgentId(newAgentId);


        List<ProductDO> newList;
        ProductListQueryBO newDto = new ProductListQueryBO();
        newDto.setAgentId(newAgentId);
        newDto.setUserType(UserType.AGENT.getCode());
        newDto.setAccreditStatus(LogicCode.NO);
        newList = productService.searchProductPrice(newDto);
        List<Long> ids = newList.stream().map(ProductDO::getId).collect(Collectors.toList());

        Boolean result = Boolean.TRUE;
        for (Long productId : productIds) {
            if (!ids.contains(productId)) {
                result = Boolean.FALSE;
            }
        }
        return result;
    }

    /**
     * @param dto
     * @Title changeAccredit
     * @Desc 修改商品授权
     * @Date 2024-09-19 15:05:02.145
     */
    @Transactional
    public void changeAccredit(ProductAccreditDTO dto) {
        Long agentId = dto.getAgentId();
        Integer status = dto.getStatus();
        Long[] productIds = dto.getProductIds();
        logs.info("【修改商品授权】代理ID:{}", agentId);
        logs.info("【修改商品授权】授权状态 0-开启 1-停用 :{}", status);
        logs.info("【修改商品授权】商品Ids:{}", productIds);
        Assert.isTrue(BeanUtils.isNotNull(agentId), "请上传代理ID");
        Assert.isTrue(BeanUtils.isNotNull(status), "请上传授权状态");
        Assert.isTrue(BeanUtils.isNotNull(productIds), "请选择商品");

        List<ProductAgentDO> updateList = new ArrayList<>();
        List<ProductAgentDO> createList = new ArrayList<>();

        for (Long productId : productIds) {
            ProductAgentDO productAgent = productAgentService.select(ProductAgentSelectQueryBO.builder().productId(productId)
                    .agentId(agentId).userType(UserType.AGENT.getCode()).build());

            // 代理所属信息
            BelongDO agentBelong = belongService.getByAgentId(UserType.AGENT.getCode(), agentId);

            // 商品信息
            ProductDO product = productService.select(productId);

            // 有授权信息 修改授权状态
            if (BeanUtils.isNotNull(productAgent)) {
                ProductAgentDO update = new ProductAgentDO();
                update.setId(productAgent.getId());
                update.setStatus(status);
                updateList.add(update);
            } else {
                // 无授权信息 新增授权
                ProductAgentDO newProductAgent = new ProductAgentDO();
                BeanUtils.clone(product, newProductAgent);
                newProductAgent.setUserType(UserType.AGENT.getCode());
                newProductAgent.setProductId(product.getId());
                newProductAgent.setBelongId(agentBelong.getBelongId());
                newProductAgent.setAgentPrice(product.getDiscountPrice());
                newProductAgent.setStatus(status);
                newProductAgent.setAgentId(agentId);
                createList.add(newProductAgent);
            }

            // 代理底下网点所属信息
            List<BelongDO> belongList = belongService.listByAgentId(UserType.SITE.getCode(), agentBelong.getBelongId());
            product.set("belongList", belongList);
            product.set("status", status);
            handleProductSite(createList, updateList, product);
        }

        for (ProductAgentDO productAgent : createList) {
            Assert.isTrue(productAgentService.create(productAgent), "新增失败");
        }

        for (ProductAgentDO productAgent : updateList) {
            Assert.isTrue(productAgentService.update(productAgent), "修改失败");
        }

        handleProductStatus(productIds);

    }

    /**
     * @param product 商品信息
     * @Title handleProductSite
     * @Desc 处理网点商品授权
     * @Date 2024-09-19 15:33:03.092
     */
    private void handleProductSite(List<ProductAgentDO> createList, List<ProductAgentDO> updateList, ProductDO product) {
        List<BelongDO> belongList = product.get("belongList");
        Integer status = product.get("status");
        for (BelongDO belong : belongList) {
            Long siteId = belong.getSiteId();
            Long belongId = belong.getBelongId();
            Long productId = product.getId();

            ProductAgentDO productAgent = productAgentService.select(ProductAgentSelectQueryBO.builder().productId(productId)
                    .mangerId(siteId).userType(UserType.SITE.getCode()).build());

            if (BeanUtils.isNotNull(productAgent)) {
                ProductAgentDO update = new ProductAgentDO();
                update.setId(productAgent.getId());
                update.setStatus(status);
                updateList.add(update);
            } else {
                ProductAgentDO create = new ProductAgentDO();
                BeanUtils.clone(product, create);
                create.setUserType(UserType.SITE.getCode());
                create.setProductId(productId);
                create.setBelongId(belongId);
                create.setStatus(status);
                create.setAgentId(belong.getAgentId());
                create.setSiteId(siteId);
                create.setUserType(UserType.SITE.getCode());
                createList.add(create);
            }
        }
    }

    /**
     * @param productIds
     * @Title handleProductStatus
     * @Desc 修改商品授权状态
     * @Date 2024-09-23 14:54:16.922
     */
    private void handleProductStatus(Long[] productIds) {
        // 更改商品的授权状态 0-指定代理商 1-全部授权
        // 找到所有代理商 与此商品的授权对比
        Integer grandType = GrantTypes.ALLOCATE.getCode();
        List<ProductDO> updateProductList = new ArrayList<>();
        for (Long productId : productIds) {
            List<AgentDTO> agentList = agentService.listDto();
            ProductAgentListQueryBO productParam = new ProductAgentListQueryBO();
            productParam.setStatus(LogicCode.NO);
            productParam.setUserType(UserType.AGENT.getCode());
            productParam.setProductId(productId);
            List<ProductAgentDO> productList = productAgentService.search(productParam);

            if (Objects.equals(agentList.size(), productList.size())) {
                grandType = GrantTypes.ALL_GRANT.getCode();
            }

            ProductDO updateProduct = new ProductDO();
            updateProduct.setId(productId);
            updateProduct.setGrantType(grandType);
            updateProductList.add(updateProduct);
        }

        for (ProductDO product : updateProductList) {
            Assert.isTrue(productService.update(product), "修改失败");
        }
    }

}